package xj.graph2d.shapes;

import java.awt.geom.CubicCurve2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;

import xj.util.gui.Point2DFloat;
import xj.util.gui.Rectangle2DFloat;

/**
 * A cubic parametric curve segment specified with float coordinates.
 */
public class CubicCurve2DFloat extends CubicCurve2D implements Serializable {
  /**
         * The X coordinate of the start point of the cubic curve segment.
         */
  public float x1;

  /**
         * The Y coordinate of the start point of the cubic curve segment.
         */
  public float y1;

  /**
         * The X coordinate of the first control point of the cubic curve
         * segment.
         */
  public float ctrlx1;

  /**
         * The Y coordinate of the first control point of the cubic curve
         * segment.
         */
  public float ctrly1;

  /**
         * The X coordinate of the second control point of the cubic curve
         * segment.
         */
  public float ctrlx2;

  /**
         * The Y coordinate of the second control point of the cubic curve
         * segment.
         */
  public float ctrly2;

  /**
         * The X coordinate of the end point of the cubic curve segment.
         */
  public float x2;

  /**
         * The Y coordinate of the end point of the cubic curve segment.
         */
  public float y2;

  /**
         * Constructs and initializes a CubicCurve with coordinates (0, 0, 0, 0,
         * 0, 0).
         */
  public CubicCurve2DFloat() {
  }

  /**
         * Constructs and initializes a <code>CubicCurve2D</code> from the
         * specified coordinates.
         * 
         * @param x1,&nbsp;y1
         *                the first specified coordinates for the start point of
         *                the resulting <code>CubicCurve2D</code>
         * @param ctrlx1,&nbsp;ctrly1
         *                the second specified coordinates for the first control
         *                point of the resulting <code>CubicCurve2D</code>
         * @param ctrlx2,&nbsp;ctrly2
         *                the third specified coordinates for the second control
         *                point of the resulting <code>CubicCurve2D</code>
         * @param x2,&nbsp;y2
         *                the fourth specified coordinates for the end point of
         *                the resulting <code>CubicCurve2D</code>
         */
  public CubicCurve2DFloat(float x1, float y1, float ctrlx1, float ctrly1,
      float ctrlx2, float ctrly2, float x2, float y2) {
    setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2);
  }

  /**
         * Returns the X coordinate of the start point in double precision.
         * 
         * @return the X coordinate of the start point of the
         *         <code>CubicCurve2D</code>.
         */
  @Override
  public double getX1() {
    return x1;
  }

  /**
         * Returns the Y coordinate of the start point in double precision.
         * 
         * @return the Y coordinate of the start point of the
         *         <code>CubicCurve2D</code>.
         */
  @Override
  public double getY1() {
    return y1;
  }

  /**
         * Returns the start point.
         * 
         * @return a {@link Point2D} that is the start point of the
         *         <code>CubicCurve2D</code>.
         */
  @Override
  public Point2D getP1() {
    return new Point2DFloat(x1, y1);
  }

  /**
         * Returns the X coordinate of the first control point in double
         * precision.
         * 
         * @return the X coordinate of the first control point of the
         *         <code>CubicCurve2D</code>.
         */
  @Override
  public double getCtrlX1() {
    return ctrlx1;
  }

  /**
         * Returns the Y coordinate of the first control point in double
         * precision.
         * 
         * @return the Y coordinate of the first control point of the
         *         <code>CubicCurve2D</code>.
         */
  @Override
  public double getCtrlY1() {
    return ctrly1;
  }

  /**
         * Returns the first control point.
         * 
         * @return a <code>Point2D</code> that is the first control point of
         *         the <code>CubicCurve2D</code>.
         */
  @Override
  public Point2D getCtrlP1() {
    return new Point2DFloat(ctrlx1, ctrly1);
  }

  /**
         * Returns the X coordinate of the second control point in double
         * precision.
         * 
         * @return the X coordinate of the second control point of the
         *         <code>CubicCurve2D</code>.
         */
  @Override
  public double getCtrlX2() {
    return ctrlx2;
  }

  /**
         * Returns the Y coordinate of the second control point in double
         * precision.
         * 
         * @return the Y coordinate of the second control point of the
         *         <code>CubicCurve2D</code>.
         */
  @Override
  public double getCtrlY2() {
    return ctrly2;
  }

  /**
         * Returns the second control point.
         * 
         * @return a <code>Point2D</code> that is the second control point of
         *         the <code>CubicCurve2D</code>.
         */
  @Override
  public Point2D getCtrlP2() {
    return new Point2DFloat(ctrlx2, ctrly2);
  }

  /**
         * Returns the X coordinate of the end point in double precision.
         * 
         * @return the X coordinate of the end point of the
         *         <code>CubicCurve2D</code>.
         */
  @Override
  public double getX2() {
    return x2;
  }

  /**
         * Returns the Y coordinate of the end point in double precision.
         * 
         * @return the Y coordinate of the end point of the
         *         <code>CubicCurve2D</code>.
         */
  @Override
  public double getY2() {
    return y2;
  }

  /**
         * Returns the end point.
         * 
         * @return a <code>Point2D</code> that is the end point of the
         *         <code>CubicCurve2D</code>.
         */
  @Override
  public Point2D getP2() {
    return new Point2DFloat(x2, y2);
  }

  /**
         * Sets the location of the endpoints and controlpoints of this
         * <code>CubicCurve2D</code> to the specified double coordinates.
         * 
         * @param x1,&nbsp;y1
         *                the first specified coordinates used to set the start
         *                point of this <code>CubicCurve2D</code>
         * @param ctrlx1,&nbsp;ctrly1
         *                the second specified coordinates used to set the first
         *                control point of this <code>CubicCurve2D</code>
         * @param ctrlx2,&nbsp;ctrly2
         *                the third specified coordinates used to set the second
         *                control point of this <code>CubicCurve2D</code>
         * @param x2,&nbsp;y2
         *                the fourth specified coordinates used to set the end
         *                point of this <code>CubicCurve2D</code>
         */
  @Override
  public void setCurve(double x1, double y1, double ctrlx1, double ctrly1,
      double ctrlx2, double ctrly2, double x2, double y2) {
    this.x1 = (float) x1;
    this.y1 = (float) y1;
    this.ctrlx1 = (float) ctrlx1;
    this.ctrly1 = (float) ctrly1;
    this.ctrlx2 = (float) ctrlx2;
    this.ctrly2 = (float) ctrly2;
    this.x2 = (float) x2;
    this.y2 = (float) y2;
  }

  /**
         * Sets the location of the endpoints and controlpoints of this curve to
         * the specified float coordinates.
         * 
         * @param x1,&nbsp;y1
         *                the first specified coordinates used to set the start
         *                point of this <code>CubicCurve2D</code>
         * @param ctrlx1,&nbsp;ctrly1
         *                the second specified coordinates used to set the first
         *                control point of this <code>CubicCurve2D</code>
         * @param ctrlx2,&nbsp;ctrly2
         *                the third specified coordinates used to set the second
         *                control point of this <code>CubicCurve2D</code>
         * @param x2,&nbsp;y2
         *                the fourth specified coordinates used to set the end
         *                point of this <code>CubicCurve2D</code>
         */
  public void setCurve(float x1, float y1, float ctrlx1, float ctrly1,
      float ctrlx2, float ctrly2, float x2, float y2) {
    this.x1 = x1;
    this.y1 = y1;
    this.ctrlx1 = ctrlx1;
    this.ctrly1 = ctrly1;
    this.ctrlx2 = ctrlx2;
    this.ctrly2 = ctrly2;
    this.x2 = x2;
    this.y2 = y2;
  }

  /**
         * Returns the bounding box of the shape.
         * 
         * @return a {@link Rectangle2D} that is the bounding box of the shape.
         */
  public Rectangle2D getBounds2D() {
    float left = Math.min(Math.min(x1, x2), Math.min(ctrlx1, ctrlx2));
    float top = Math.min(Math.min(y1, y2), Math.min(ctrly1, ctrly2));
    float right = Math.max(Math.max(x1, x2), Math.max(ctrlx1, ctrlx2));
    float bottom = Math.max(Math.max(y1, y2), Math.max(ctrly1, ctrly2));
    return new Rectangle2DFloat(left, top, right - left, bottom - top);
  }
}
